﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Model
{
    /// <summary>
    /// 解析状态
    /// </summary>
    internal enum ParserState
    {
        PacketSize,
        PacketBody
    }

    /// <summary>
    /// 一个数据包结构 | 长度 2字节 | 类型 2字节 | 数据 |
    /// </summary>
    public struct Packet
    {
        public byte[] Bytes { get; set; }
        public int Length { get; set; }

        public Packet(int len)
        {
            this.Length = 0;
            this.Bytes = new byte[len];
        }

        public Packet(byte[] bytes)
        {
            this.Bytes = bytes;
            this.Length = bytes.Length;
        }
    }

    /// <summary>
    /// 解析包
    /// </summary>
    public class PacketParser
    {
        private readonly Circularbuffer ringBuffer;
        private bool isOK;
        private ushort packetSize;
        private ParserState parserState;
        private Packet packet = new Packet(8 * 1024);
        
        public PacketParser(Circularbuffer buffer)
        {
            this.ringBuffer = buffer;
        }

        public bool Parser()
        {
            if (this.isOK)
                return true;

            bool finish = false;
            while (!finish)
            {
                switch (parserState)
                {
                    case ParserState.PacketSize:

                        // 判断数据是否够基本长度
                        if(this.ringBuffer.Count < 2)
                        {
                            finish = true;
                        }
                        else
                        {
                            this.ringBuffer.RecvFrom(this.packet.Bytes, 2);
                            this.packetSize = BitConverter.ToUInt16(this.packet.Bytes, 0);
                            if(this.packetSize > 60000)
                            {
                                throw new Exception("packet too large，size:" + packetSize);
                            }
                            this.parserState = ParserState.PacketBody;
                        }
                        break;
                    case ParserState.PacketBody:
                        // 判断缓存区的数据是否够一个包的长度
                        if(this.ringBuffer.Count < this.packetSize)
                        {
                            finish = true;
                        }
                        else
                        {
                            this.ringBuffer.RecvFrom(this.packet.Bytes, this.packetSize);
                            packet.Length = this.packetSize;
                            this.isOK = true;
                            parserState = ParserState.PacketSize;
                            finish = true;
                        }
                        break;
                }
            }
            return isOK;
        }

        public Packet GetPacket()
        {
            this.isOK = false;
            return this.packet;
        }
    }
}
